﻿using System.Collections;
using Basic.FormCollect;
using Basic.FormModel.DB;
using Basic.FormModel.Form;
using Basic.FormModel.PhyColumn;
using Basic.FormRemoteModel;
using Basic.FormRemoteModel.PhyFormInter;
using Basic.FormRemoteModel.PhyFormInter.Model;
using Basic.FormRemoteModel.QueryInter.Model;
using Basic.UserFormService.Interface;
using Basic.UserFormService.Model.PhyForm;
using WeDonekRpc.Helper;
using WeDonekRpc.Helper.Validate;

namespace Basic.UserFormService.lmpl
{
    internal class PhyFormService : IPhyFormService
    {
        private readonly IPhysicalFormGroupCollect _PhyGroup;
        private readonly IPhysicalTableCollect _PhyTable;
        private readonly IPhysicalColumnCollect _PhyColumn;
        private readonly ICustomFormCollect _Form;

        public PhyFormService ( IPhysicalFormGroupCollect phyGroup,
            IPhysicalTableCollect phyTable,
            IPhysicalColumnCollect phyColumn,
            ICustomFormCollect form )
        {
            this._PhyGroup = phyGroup;
            this._PhyTable = phyTable;
            this._PhyColumn = phyColumn;
            this._Form = form;
        }

        public void Sync ( long id )
        {
            DBCustomForm form = this._Form.Get(id);
            if ( form.FormType != FormType.代理表单 )
            {
                throw new ErrorException("form.no.is.physical");
            }
            PhyFormGroup group = this._PhyGroup.Get<PhyFormGroup>(form.PhyGroupId.Value);
            PhyFormTable[] table = new GetPhyTableBody
            {
                TableName = form.TableName
            }.Send(group.SysTypeVal);
            this._PhyTable.Sync(id, table);
        }
        public Dictionary<long, FormVal> GetValues ( FormBase form, FormValsGetArg arg )
        {
            Dictionary<long, FormVal> vals = new Dictionary<long, FormVal>();
            this.LoadValues(form, arg.LinkPK, arg.LinkType, arg.Column, vals);
            return vals;
        }
        public void LoadValues ( FormBase form, long lnkPk, string linkType, KeyValuePair<long, string>[] column, Dictionary<long, FormVal> vals )
        {
            PhyColumn[] cols = this._PhyColumn.Gets<PhyColumn>(column.ConvertAll(a => a.Key));
            if ( cols.IsNull() )
            {
                throw new ErrorException("form.phy.column.not.find");
            }
            PhyFormGroup group = this._PhyGroup.Get<PhyFormGroup>(form.PhyGroupId.Value);
            PhyTable[] tables = this._PhyTable.Gets<PhyTable>(cols.ConvertAll(a => a.PhyTableId));
            PhyFormColValue[] res = new GetPhyTableValues
            {
                Arg = new PhyValuesGetArg
                {
                    LinkType = linkType,
                    LinkPk = lnkPk,
                    PhyTableName = form.TableName,
                    Cols = cols.ConvertAll(a => new PhyTableCol
                    {
                        ColName = a.Name,
                        TableName = tables.Find(c => c.Id == a.PhyTableId, c => c.TableName),
                        Key = a.Id,
                        Keywords = column.Find(c => c.Key == a.Id, c => c.Value),
                    })
                }
            }.Send(group.SysTypeVal);
            cols.ForEach(a =>
            {
                PhyFormColValue t = res.Find(c => c.Key == a.Id);
                if ( t == null )
                {
                    vals.Add(a.Id, new FormVal
                    {
                        DataType = a.DataType,
                        IsNull = true
                    });
                }
                else
                {
                    vals.Add(a.Id, this._Format(t, a));
                }
            });
        }
        private FormVal _Format ( PhyFormValue val, PhyColumn col )
        {
            FormVal res = new FormVal
            {
                DataType = col.DataType,
                IsNull = val.IsNull,
                InactiveText = val.InactiveText,
                ActivateText = val.ActivateText,
                NumStep = val.NumStep,
                FuncType = col.FuncType.ToDataFuncType(),
            };
            if ( col.ColumnSet != null )
            {
                res.ActivateText = col.ColumnSet.ActivateText;
                res.InactiveText = col.ColumnSet.InactiveText;
                res.NumStep = col.ColumnSet.NumStep;
                res.DicId = col.ColumnSet.DicId;
                res.DirKey = col.ColumnSet.DirKey;
                res.Items = col.ColumnSet.Items;
            }
            if ( res.IsNull )
            {
                return res;
            }
            if ( col.DataType == FormRecordDataType.Date )
            {
                res.LongVal = Convert.ToDateTime(val.Value).Date.ToLong();
            }
            else if ( col.DataType == FormRecordDataType.DateTime )
            {
                res.LongVal = Convert.ToDateTime(val.Value).ToLong();
            }
            else if ( col.DataType == FormRecordDataType.Bool )
            {
                res.BoolVal = Convert.ToBoolean(val.Value);
            }
            else if ( col.DataType == FormRecordDataType.Long )
            {
                res.LongVal = Convert.ToInt64(val.Value);
            }
            else if ( col.DataType == FormRecordDataType.Number )
            {
                res.NumVal = Convert.ToDecimal(val.Value);
            }
            else if ( col.DataType == FormRecordDataType.Array )
            {
                if ( val.Value is IList k )
                {
                    string[] vals = new string[k.Count];
                    int i = 0;
                    foreach ( object? data in k )
                    {
                        vals[i++] = data.ToString();
                    }
                    res.Vals = vals;
                }
            }
            else if ( col.DataType == FormRecordDataType.Time )
            {
                string str = Convert.ToString(val.Value);
                if ( str.Validate(ValidateFormat.小时分) )
                {
                    string[] t = str.Split(':');
                    res.LongVal = ( int.Parse(t[0]) * 60 ) + int.Parse(t[1]);
                }
                else
                {
                    DateTime time = DateTime.Parse(str);
                    res.LongVal = ( time.Hour * 60 ) + time.Minute;
                }
            }
            else
            {
                res.StrVal = Convert.ToString(val.Value);
            }
            return res;
        }

        public FormVal GetValue ( FormBase form, FormValGetArg arg )
        {
            PhyColumn col = this._PhyColumn.Get<PhyColumn>(arg.ColumnId);
            PhyTable table = this._PhyTable.Get<PhyTable>(col.PhyTableId);
            PhyFormGroup group = this._PhyGroup.Get<PhyFormGroup>(form.PhyGroupId.Value);
            PhyFormValue val = new GetPhyTableValue
            {
                Arg = new PhyValueGetArg
                {
                    LinkType = arg.LinkType,
                    LinkPk = arg.LinkPK,
                    Keywords = arg.Keywords,
                    PhyTableName = table.TableName,
                    TableName = table.TableName,
                    ColName = col.Name
                }
            }.Send(group.SysTypeVal);
            return this._Format(val, col);
        }
    }
}
